#include "IPv6Address.h"
#include <stdexcept>
#include <string.h>

IPv6Address::IPv6Address()
{
}

IPv6Address::IPv6Address( const struct sockaddr_in6 &address )
{
	setFromSockAddr( address );
}

IPv6Address::~IPv6Address()
{
}

void IPv6Address::setFromSockAddr( const struct sockaddr_in6 &address )
{
	address_ = address;
}

socklen_t IPv6Address::sockaddrSize() const 
{
	return sizeof( address_ );
}

struct sockaddr_in6* IPv6Address::sockaddr() 
{
	return &address_;
}

void IPv6Address::setAddress( const std::string &address )
{
	int result = inet_pton( AF_INET6, address.c_str(), &address_.sin6_addr );
	if( result < 1 )
	{
		if( result == 0 )
		{
			throw std::runtime_error("ERROR: Bad address");
		}
		else
		{
			throw std::runtime_error( "inet_pton failure" );
		}
	}
}

std::string IPv6Address::address() const
{
	char address[ INET6_ADDRSTRLEN ];
	memset( address, 0, INET6_ADDRSTRLEN ); //NULL out string
	inet_ntop( AF_INET6, &(address_.sin6_addr), address, sizeof( address_ ) );
	return std::string( address );
}

void IPv6Address::setPort( const std::string &port )
{
	uint16_t portnum = ss_atoi<uint16_t>(port);
	setPort( portnum );
}

void IPv6Address::setPort( const uint16_t &port )
{
	address_.sin6_port = htons( port );
}

std::string IPv6Address::port() const 
{
	uint16_t port = portNum();
	return ss_itoa(port);
}

uint16_t IPv6Address::portNum() const
{
	return ntohs(address_.sin6_port);
}

void IPv6Address::setFamily( const uint8_t &family )
{
	address_.sin6_family = family;
}

uint8_t IPv6Address::family() const
{
	return address_.sin6_family;
}
